"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

from django.db import models
from django.db.models import Max, Q
from django.contrib.auth.models import Permission
import random, string
from django.utils.translation import gettext_lazy as _
from siriuso.models.postgres import CallableEncoder
from siriuso.utils import default_lingvo, perms
from main.models import SiriusoBazaAbstrakta3
from main.models import SiriusoTipoAbstrakta
from main.models import Uzanto
import sys


# Типы Тамагочи, использует абстрактный класс SiriusoTipoAbstrakta
class TamagocxiTipo(SiriusoTipoAbstrakta):

    # название в таблице названий типов, от туда будет браться название с нужным языковым тегом
    nomo = models.JSONField(verbose_name=_('Nomo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'tamagocxi_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de tamagocxi')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de tamagocxi')
        # права
        permissions = (
            ('povas_vidi_tipon', _('Povas vidi tipon')),
            ('povas_krei_tipon', _('Povas krei tipon')),
            ('povas_forigi_tipon', _('Povas forigu tipon')),
            ('povas_shanghi_tipon', _('Povas ŝanĝi tipon')),
        )

    @staticmethod
    def _get_perm_cond(user_obj):
        return Q()


# Степени Тамагочи, использует абстрактный класс SiriusoBazaAbstrakta3
class TamagocxiGrado(SiriusoBazaAbstrakta3):

    # степень
    grado = models.IntegerField(_('Grado'), blank=False, default=1)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'tamagocxi_gradoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Grado de tamagocxi')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Gradoj de tamagocxi')
        # права
        permissions = (
            ('povas_vidi_gradon', _('Povas vidi gradon')),
            ('povas_krei_gradon', _('Povas krei gradon')),
            ('povas_forigi_gradon', _('Povas forigu gradon')),
            ('povas_shanghi_gradon', _('Povas ŝanĝi gradon')),
        )

    @staticmethod
    def _get_perm_cond(user_obj):
        return Q()

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле grado этой модели
        return '{}'.format(self.grado)


# Виды Тамагочи, использует абстрактный класс SiriusoTipoAbstrakta
class TamagocxiSpeco(SiriusoTipoAbstrakta):

    # название в таблице названий видов Тамагочи, от туда будет браться название с нужным языковым тегом
    nomo = models.JSONField(verbose_name=_('Nomo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание в таблице описаний видов Тамагочи, от туда будет браться описание с нужным языковым тегом
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'tamagocxi_speco'
        # читабельное название модели, в единственном числе
        verbose_name = _('Speco de tamagocxi')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Specoj de tamagocxi')
        # права
        permissions = (
            ('povas_vidi_specon', _('Povas vidi specon')),
            ('povas_krei_specon', _('Povas krei specon')),
            ('povas_forigi_specon', _('Povas forigu specon')),
            ('povas_shanghi_specon', _('Povas ŝanĝi specon')),
        )

    @staticmethod
    def _get_perm_cond(user_obj):
        return Q()


# Генерация случайного названия и переименование загружаемых картинок аватар советов
def tamagocxi_bildo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'tamagocxi/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Перечень Тамагочи (ими будет награждение), использует абстрактный класс SiriusoBazaAbstrakta3
class TamagocxiPremio(SiriusoBazaAbstrakta3):

    # ID записи
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # вид Тамагочи
    speco = models.ForeignKey(TamagocxiSpeco, verbose_name=_('Speco'), blank=False, default=None,
                              on_delete=models.CASCADE)

    # тип Тамагочи
    tipo = models.ForeignKey(TamagocxiTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # степень Тамагочи
    grado = models.ForeignKey(TamagocxiGrado, verbose_name=_('Grado'), blank=False, default=None,
                              on_delete=models.CASCADE)

    # миниатюра изображения Тамагочи (размер 50х50)
    bildo_min = models.ImageField(_('Miniaturo'), upload_to=tamagocxi_bildo_nomo, blank=True)

    # информационное изображение
    bildo_info = models.ImageField(_('Infa bildo'), upload_to=tamagocxi_bildo_nomo, blank=True)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'tamagocxi_premioj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Premio')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tamagocxi')
        # права
        permissions = (
            ('povas_vidi_premiojn', _('Povas vidi premiojn')),
            ('povas_krei_premiojn', _('Povas krei premiojn')),
            ('povas_forigi_premiojn', _('Povas forigu premiojn')),
            ('povas_shanghi_premiojn', _('Povas ŝanĝi premiojn')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле speco этой модели
        return '{} {} {}'.format(self.speco, self.tipo, self.grado)

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(TamagocxiPremio, self).save(force_insert=force_insert, force_update=force_update,
                                           using=using, update_fields=update_fields)

    def _get_user_permissions(self, user_obj):
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            all_perms = set(perms.user_registrita_perms(apps=('tamagocxi',)))

            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'tamagocxi.povas_vidi_premiojn', 'tamagocxi.povas_krei_premiojn',
                'tamagocxi.povas_forigi_premiojn', 'tamagocxi.povas_shanghi_premiojn'
            ))

            user_perms = Permission.objects.filter(content_type__app_label='tamagocxi', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            if (perms.has_registrita_perm('tamagocxi.povas_vidi_premiojn')
                    or user_obj.has_perm('tamagocxi.povas_vidi_premiojn')):
                cond = Q()
            else:
                cond = Q(uuid__isnull=True)

        else:
            if perms.has_neregistrita_perm('tamagocxi.povas_vidi_premiojn'):
                cond = Q()
            else:
                cond = Q(uuid__isnull=True)

        return cond

# Условия награждения (справочник), использует абстрактный класс SiriusoTipoAbstrakta
class TamagocxiKondicho(SiriusoTipoAbstrakta):

    # название в таблице названий условий награждения, от туда будет браться название с нужным языковым тегом
    nomo = models.JSONField(verbose_name=_('Nomo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание в таблице описаний условий награждения, от туда будет браться описание с нужным языковым тегом
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'tamagocxi_kondichoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kondiĉo de premiado')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kondiĉoj de premiadoj')
        # права
        permissions = (
            ('povas_vidi_kondichojn', _('Povas vidi kondichojn')),
            ('povas_krei_kondichojn', _('Povas krei kondichojn')),
            ('povas_forigi_kondichojn', _('Povas forigu kondichojn')),
            ('povas_shanghi_kondichojn', _('Povas ŝanĝi kondichojn')),
        )
    def _get_user_permissions(self, user_obj):
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            all_perms = set(perms.user_registrita_perms(apps=('tamagocxi',)))

            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'tamagocxi.povas_vidi_kondichojn', 'tamagocxi.povas_krei_kondichojn',
                'tamagocxi.povas_forigi_kondichojn', 'tamagocxi.povas_shanghi_kondichojn'
            ))

            user_perms = Permission.objects.filter(content_type__app_label='tamagocxi', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            if (perms.has_registrita_perm('tamagocxi.povas_vidi_kondichojn')
                    or user_obj.has_perm('tamagocxi.povas_vidi_kondichojn')):
                cond = Q()
            else:
                cond = Q(uuid__isnull=True)

        else:
            if perms.has_neregistrita_perm('tamagocxi.povas_vidi_kondichojn'):
                cond = Q()
            else:
                cond = Q(uuid__isnull=True)

        return cond


# Награждение (перечень всех присвоений Тамагочи), использует абстрактный класс SiriusoBazaAbstrakta3
class TamagocxiPremiado(SiriusoBazaAbstrakta3):

    # ID записи
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # награждённый (человек, которому вручили Тамагочи)
    premiita = models.ForeignKey(Uzanto, verbose_name=_('Premiita'), blank=False, default=None,
                                 related_name='%(app_label)s_%(class)s_premiita', on_delete=models.CASCADE)

    # Тамагочи (из перечня Тамагоч)
    premio = models.ForeignKey(TamagocxiPremio, verbose_name=_('Premio'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # причина награждания (какое условие было выполнено)
    kondicho = models.ForeignKey(TamagocxiKondicho, verbose_name=_('Kondiĉo'), blank=False, default=None,
                                 on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'tamagocxi_premiadoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Premiado')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Premiadoj')
        # права
        permissions = (
            ('povas_vidi_premiadojn', _('Povas vidi premiadojn')),
            ('povas_krei_premiadojn', _('Povas krei premiadojn')),
            ('povas_forigi_premiadojn', _('Povas forigu premiadojn')),
            ('povas_shanghi_premiadojn', _('Povas ŝanĝi premiadojn')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поля premiita и premio этой модели
        return '{} {}'.format(self.premiita, self.premio)

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(TamagocxiPremiado, self).save(force_insert=force_insert, force_update=force_update,
                                           using=using, update_fields=update_fields)

    def _get_user_permissions(self, user_obj):
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            all_perms = set(perms.user_registrita_perms(apps=('tamagocxi',)))

            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'tamagocxi.povas_vidi_premiadojn', 'tamagocxi.povas_krei_premiadojn',
                'tamagocxi.povas_forigi_premiadojn', 'tamagocxi.povas_shanghi_premiadojn'
            ))

            user_perms = Permission.objects.filter(content_type__app_label='tamagocxi', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            if (perms.has_registrita_perm('tamagocxi.povas_vidi_premiadojn')
                    or user_obj.has_perm('tamagocxi.povas_vidi_premiadojn')):
                cond = Q()
            else:
                cond = Q(uuid__isnull=True)

        else:
            if perms.has_neregistrita_perm('tamagocxi.povas_vidi_premiadojn'):
                cond = Q()
            else:
                cond = Q(uuid__isnull=True)

        return cond
